package stdx;

import java.io.Closeable;
import java.util.ArrayList;

public abstract class ResPool{
	public static interface Resource extends Closeable{
		public void setPool(ResPool pool);
	}

	class Data{
		private int num = 0;
		private long utime = 0;
		private Boolean idle = true;
		private Resource conn = null;

		void close(){
			if (conn == null) return;
			conn.setPool(null);
			Utils.Close(conn);
			conn = null;
		}
		void release(){
			if (checkSuccess(conn)){
				idle = true;
			}
			else{
				close();
			}
		}
		Closeable get() throws Exception{
			if (conn == null){
				num = 0;
				conn = create();
				conn.setPool(ResPool.this);
			}

			utime = System.currentTimeMillis();
			idle = false;
			++num;

			return conn;
		}
	}

	int maxlen = 8;
	int timeout = 60;
	ArrayList<Data> vec = new ArrayList<Data>();

	public abstract Resource create() throws Exception;
	public abstract boolean checkSuccess(Closeable conn);

	public void destroy(){
		synchronized(vec){
			for (Data item : vec){
				if (item.idle) item.close();
				item.utime = 0;
			}
		}
	}
	public void setLength(int maxlen){
		this.maxlen = maxlen;
	}
	public void setTimeout(int timeout){
		this.timeout = timeout;
	}
	public void release(Closeable conn){
		synchronized(vec){
			for (Data item : vec){
				if (conn == item.conn){
					item.release();
					return;
				}
			}
		}

		Utils.Close(conn);
	}
	public Closeable get() throws Exception{
		long start = System.currentTimeMillis();

		while (true){
			long now = System.currentTimeMillis();

			synchronized(vec){
				Data res = null;

				for (Data item : vec){
					if (item.idle || item.conn == null){
						if (item.num < 100 && item.utime + timeout * 1000 > now) return item.get();
						item.close();
						res = item;
					}
				}

				if (res == null){
					if (vec.size() >= maxlen){
						if (start + 1000 < System.currentTimeMillis()) throw new Exception("resource busy");
						Thread.sleep(10);
						continue;
					}

					vec.add(res = new Data());
				}

				return res.get();
			}
		}
	}
}
